<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="zh" xml:lang="zh" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Guideline: 扩展关系</title>
<meta name="uma.type" content="Guideline">
<meta name="uma.name" content="extend-relationship">
<meta name="uma.presentationName" content="扩展关系">
<meta name="element_type" content="other">
<meta name="filetype" content="description">
<meta name="role" content="">
<link rel="StyleSheet" href="./../../../css/default.css" type="text/css">
<script src="./../../../scripts/ContentPageResource.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/ContentPageSection.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/ContentPageSubSection.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/ContentPageToolbar.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/contentPage.js" type="text/javascript" language="JavaScript"></script><script type="text/javascript" language="JavaScript">
					var backPath = './../../../';
					var imgPath = './../../../images/';
					var nodeInfo=null;
					contentPage.preload(imgPath, backPath, nodeInfo,  '', false, false, false);
				</script>
</head>
<body>
<div id="breadcrumbs"></div>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td valign="top"><a name="Top"></a>
<div id="page-guid" value="3.679940320411645E-305"></div>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td class="pageTitle" nowrap="true">Guideline: 扩展关系</td><td width="100%">
<div align="right" id="contentPageToolbar"></div>
</td><td width="100%" class="expandCollapseLink" align="right"><a name="mainIndex" href="./../../../index.htm"></a><script language="JavaScript" type="text/javascript" src="./../../../scripts/treebrowser.js"></script></td>
</tr>
</table>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="pageTitleSeparator"><img src="./../../../images/shim.gif" alt="" title="" height="1"></td>
</tr>
</table>
<div class="overview">
<table width="97%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="50"><img src="./../../../images/guidance.gif" alt="" title=""></td><td>
<table class="overviewTable" border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top">扩展关系将扩展用例与基本用例连接起来。 本指南说明如何使用此关系。</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<div class="sectionHeading">Relationships</div>
<div class="sectionContent">
<table class="sectionTable" border="0" cellspacing="0" cellpadding="0">
<tr valign="top">
<th class="sectionTableHeading" scope="row">Related Elements</th><td class="sectionTableCell">
<ul>
<li>
<a href="./../../../rup/tasks/structure_use_case_model_93D8F44.html" guid="{F7D9D038-B184-43CC-9353-15BA154F87B5}">构造用例模型</a>
</li>
<li>
<a href="./../../../rup/domains/requirements_58267518.html" guid="_KVkLoN7HEdm8G6yT7-Wdqw">需求</a>
</li>
<li>
<a href="./../../../rup/workproducts/rup_usecase_model_EF15E534.html" guid="{9C66F2EC-EDEB-4369-9AFB-04B9E7CBCB8E}">用例模型</a>
</li>
</ul>
</td>
</tr>
</table>
</div>
<div class="sectionHeading">Main Description</div>
<div class="sectionContent">
<table class="sectionTable" border="0" cellspacing="0" cellpadding="0">
<tr valign="top">
<td class="sectionTableSingleCell"><a id="Top" name="Top"></a><a key="扩展关系（extend-relationship）" text="指南" name="XE_extend-relationship__guidelines_for" id="XE_extend-relationship__guidelines_for" class="index"></a> 
<h3>
    <a id="Explanation" name="Explanation">说明</a>
</h3>
<p>
    扩展关系将扩展用例与基本用例连接起来。 通过在基本用例中引用扩展点，可以定义在基本用例的哪些位置插入扩展用例（关于扩展点的讨论请参阅<a class="elementLinkWithType" href="./../../../rup/guidances/guidelines/use_case_CC89870D.html" guid="4.1983217662266927E-305">Guideline: 用例</a>）。
    扩展用例常常是抽象的，但并不一定是抽象的。
</p>
<p>
    可将扩展用于以下几种情况：
</p>
<ul>
    <li>
        显示用例的一部分是可选的系统行为，或者可能是可选的系统行为。通过这种方式，您可将模型中的可选行为与强制行为分开来。
    </li>
    <li>
        显示某个子流只在一定的（有时是异常的）条件下执行，例如触发警报时。
    </li>
    <li>
        显示可能存在一组行为段，其中的一个或几个行为段可以在基本用例中的扩展点处插入。 插入的行为段（以及它们的插入顺序）将取决于执行基本用例期间与参与者的交互。
    </li>
</ul>
<p>
    扩展是有条件的，这意味着它的执行取决于在执行基本用例期间发生了什么。 基本用例不控制扩展的执行条件 － 这些条件在扩展关系内有所描述。 扩展用例可以访问和修改基本用例的属性。 但基本用例却看不到扩展用例，也不能访问它们的属性。
</p>
<p>
    基本用例可通过扩展进行隐式修改。您还可以说基本用例定义了一个模块化框架，可向其添加扩展，但基本用例根本无法看到具体的扩展。
</p>
<p>
    基本用例内部就其本身而言应该是完整的，这意味着它在不引用任何扩展的情况下应是可理解的和有意义的。 但是，基本用例并非独立于扩展，因为如果不遵循扩展，它就不能执行。
</p>
<h5>
    示例：
</h5>
<p class="example" align="center">
    <img height="186" alt="附带文本中描述的图。" src="./../../../rup/guidances/guidelines/resources/extend1.gif" width="300" />
</p>
<p class="picturetext">
    用例“拨打会议电话”和“显示致电者身份”都是基本用例“拨打电话”的扩展。
</p>
<p class="example">
    在电话系统中，提供给用户的主要服务是由用例“拨打电话”来表现的。可选服务的示例有：
</p>
<ul>
    <li>
        <p class="example">
            能够将第三方添加到电话对话中（拨打会议电话）。
        </p>
    </li>
    <li>
        <p class="example">
            允许接收方知道致电者的身份（显示致电者身份）。
        </p>
    </li>
</ul>
<p class="example">
    我们可以将这些可选服务所需要的行为表现为基本用例“拨打电话”的扩展用例。 这是扩展关系的正确用法：因为“拨打电话”本身就是有意义的，您无需阅读扩展用例的描述就能理解基本用例的主要用途，且扩展用例具有可选的特征。
</p>
<p>
    如果基本用例和“基本加扩展”用例必须明显是可实例化的，或者如果您想要通过添加来修改基本用例中的行为，则应使用用例泛化关系（请参阅<a class="elementLinkWithUserText" href="./../../../rup/guidances/guidelines/use-case_generalization_B301F53B.html" guid="3.7061366529594173E-305">工作产品指南：用例泛化关系</a>）。
</p>
<p>
    扩展用例可以由一个或多个插入段组成，每个插入段都可以在其中构建备选路径。 这些插入段递增地修改基本用例的行为。 扩展用例中的每个插入段都可以在基本用例中的单独位置插入。
    这意味着扩展关系具有一系列对扩展点的引用，引用的数量与扩展用例中插入段的数量相等。每个扩展点都必须定义在基本用例中。
</p>
<p>
    一个基本用例包含几个扩展关系，这意味着一个用例实例在其生命期内可以遵循多个扩展。 一个扩展用例可以扩展到几个基本用例中，但这并不表示这几个基本用例之间存在任何依赖关系。
    甚至在同样的扩展用例和基本用例之间也可以有多个扩展关系，前提是扩展是在基本用例的不同位置插入的。 这意味着不同的扩展关系需要引用基本用例中的不同扩展点。 扩展用例本身可以是扩展关系、包含关系或泛化关系中的基本用例。
    例如，这意味着扩展用例可以嵌套方式扩展其他扩展用例。
</p>
<h3>
    <a id="Executing the Extension" name="Executing the Extension">执行扩展</a>
</h3>
<p>
    如果执行基本用例的某一用例实例触及基本用例中的某个位置，该位置定义了扩展点，则会评估相应扩展关系的条件。 如果条件为真或不存在，用例实例将遵循扩展（或者在扩展内部与扩展点相对应的插入段）。 如果扩展关系的条件为假，则不执行扩展。
</p>
<p>
    就象所有用例一样，扩展用例可以有基本事件流和备选事件流（关于事件流结构的讨论请参阅<a class="elementLinkWithType" href="./../../../rup/guidances/guidelines/use_case_CC89870D.html" guid="4.1983217662266927E-305">Guideline: 用例</a>）。用例实例将在扩展中采用哪条确切路径，这取决于之前在扩展中发生了什么（用例实例的状态），还取决于在执行扩展时与参与者的交互中发生了什么。 一旦用例实例执行了此扩展，用例实例会在基本用例停止之处继续执行基本用例。
</p>
<p align="center">
    <img height="224" alt="附带文本中描述的图。" src="./../../../rup/guidances/guidelines/resources/extend2.gif" width="312" />
</p>
<p class="picturetext">
    遵循基本用例及其扩展的用例实例。
</p>
<p>
    扩展用例可以有多个插入段，每个插入段都与其自身在基本用例中的扩展点相关。 如果是这种情况，用例实例将恢复基本用例的执行，并继续在扩展关系中指定的下一个扩展点执行。
    在该点，它将执行扩展用例的下一个插入段。重复该操作，直到执行完最后一个插入段。 请注意，只在第一个扩展点检查扩展关系的条件 － 如果条件为真，用例实例则必须执行所有的插入段。
</p>
<p align="center">
    <img height="224" alt="附带文本中描述的图。" src="./../../../rup/guidances/guidelines/resources/extend3.gif" width="317" />
</p>
<p class="picturetext">
    遵循基本用例和扩展用例（后者具有两个插入段）的用例实例。
</p>
<p>
    扩展关系的多重性将限制整个扩展中可能发生的重复次数。请注意，重复的是整个扩展（受多重性的限制），而不仅仅是一个插入段。
</p>
<h3>
    <a id="Documenting the Extend-Relationship" name="Documenting the Extend-Relationship">记录扩展关系</a> <a href="#Top"><img     height="20" alt="回到页首" src="./../../../rup/resources/top.gif" width="26" border="0" /></a>
</h3>
<p>
    根据基本用例的属性描述扩展的条件。您还可以选择省略条件，在这种情况下将始终执行扩展。
</p>
<p>
    每个扩展关系都有一系列对基本用例中（一个或多个）扩展点的引用。 扩展点是按名称引用的。如果扩展用例有多个插入段，则您需要指定哪个插入段对应于哪个扩展点。 您还需要指定每个插入段由扩展用例的哪些步骤或子流构成。
</p>
<h5>
    示例：
</h5>
<p class="example">
    在电话系统中，用例“拨打电话”可以通过抽象用例“显示致电者身份”进行扩展。 这是一项可选服务，通常称为“致电者身份”，接收方可能以请求也可能还未请求该服务。从“显示致电者身份”到“拨打电话”的扩展关系的描述应显示如下：
</p>
<p class="example">
    <b>条件：</b>接收方必须订购了“致电者身份”服务。
</p>
<p class="example">
    <b>扩展点：</b>显示身份 － 插入整个“显示致电者身份”用例。
</p>
<p>
    您可以赋予该扩展关系多重性，如果省略，则假定多重性为一。
</p>
<h3>
    <a id="Example of Use" name="Example of Use">使用示例</a>
</h3>
<p>
    请考虑以下这个简单的电话系统：
</p>
<p align="center">
    <img height="182" alt="附带文本中描述的图。" src="./../../../rup/guidances/guidelines/resources/extend4.gif" width="271" />
</p>
<p class="picturetext" align="center">
    抽象用例“拨打会议电话”是对用例“拨打电话”的扩展。
</p>
<p>
    在此模型中，我们的家庭电话系统（即基本呼叫服务）的简单表示在用例“拨打电话”中有所描述。基本事件流的分步概述将显示如下：
</p>
<ol>
    <li>
        致电者拿起话筒。
    </li>
    <li>
        系统发出拨号音。
    </li>
    <li>
        致电者拨一个数字。
    </li>
    <li>
        系统关闭拨号音。
    </li>
    <li>
        致电者拨号码的剩余数字。
    </li>
    <li>
        系统分析数字，确定接收方的网络地址。
    </li>
    <li>
        系统分析这些数字，确定接收方在网络中所处的位置。
    </li>
    <li>
        系统确定是否能建立到接收方的虚电路。
    </li>
    <li>
        如果可以建立虚电路，系统会使接收方的电话响铃，并在致电者的电话上表现出对方已响铃。
    </li>
    <li>
        接收方应答电话后，系统禁用致电者电话上的铃声，停止使接收方的电话铃响，并完成虚电路。
    </li>
    <li>
        系统启动帐单记录，记录电话的开始时间、电话的结束点以及致电者的客户信息。
    </li>
    <li>
        本次电话持续一段时间。当致电者或接收方中的任一方挂断本地电话时，系统则记录本次电话的结束时间，并释放支持虚电路所需的所有资源。然后用例结束。
    </li>
</ol>
<p>
    要向此系统添加功能，以允许致电者或接收方将第三方连接到电话对话中（通常称为“电话会议”），则需要向事件流添加行为。一种备用方法，也是我们首先会想到的，就是直接将两者的差别放到“拨打电话”中。 我们可以使用备用事件流对这些差别建模，如<a class="elementLinkWithType" href="./../../../rup/guidances/guidelines/use_case_CC89870D.html" guid="4.1983217662266927E-305">Guideline: 用例</a>中所述。 该解决方案适用于最简单的添加，其中所添加的功能不会与用例的原始含义混淆或使原始含义模糊不清。
    另一种备用方法是将差别分离为一个称为“拨打会议电话”的抽象扩展用例，该抽象扩展用例扩展了基本用例。
</p>
<p>
    “拨打电话”用例将具有以下添加项：
</p>
<blockquote>
    <p>
        <b><u>扩展点：<br />
        </u>会议电话</b>在第 11 步之后进行。
    </p>
</blockquote>
<p>
    随后，扩展用例“拨打会议电话”可以描述为：
</p>
<blockquote>
    <p>
        <b><u>“拨打会议电话”用例<br />
        </u></b>此用例扩展了“拨打电话”。它在扩展点“电话会议”处插入。<br />
        <u>基础流：<br />
        </u>1. 致电者压下挂断器、链环或闪动按键。<br />
        2. 系统发出三声短促的蜂鸣声以确认。<br />
        3 到 12.&lt;这些步骤与基本用例中的步骤 3 到 12 完全相同&gt;<br />
        13. 致电者从“拨打电话”用例重新连接到接收方。
    </p>
</blockquote>
<p>
    步骤 3 到 12 与基本用例中完全相同，我们不希望如此。解决该问题的一种方法是抽出共同的部分，作为一个包含用例（请参阅<a class="elementLinkWithType" href="./../../../rup/guidances/guidelines/include-relationship_5AE2718.html" guid="7.259881398615376E-305">Guideline: 包含关系</a>）。
</p><br />
<br /></td>
</tr>
</table>
</div>
<table class="copyright" border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="copyright">Copyright &copy; 2008 版权所有 东软集团股份有限公司&nbsp; 联系邮箱:<a href="mailto:tcoe@neusoft.com">tcoe@neusoft.com</a></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
<script type="text/javascript" language="JavaScript">
				contentPage.onload();
			</script>
</html>
